package com.dingwen.treasure.file.generate.component;

import cn.hutool.core.util.StrUtil;
import com.dingwen.treasure.file.generate.util.FreeMarkerUtil;
import lombok.Cleanup;
import lombok.SneakyThrows;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * 文件组件
 *
 * @author dingwen
 * @date 2022/10/27
 */
@Component
public class FileComponent {


    @Resource
    private FreeMarkerUtil freeMarkerUtil;


    /**
     * 下载文件
     *
     * @param httpServletResponse 响应
     * @param fileName            文件名称
     */
    public void download(HttpServletResponse httpServletResponse, String fileName, String fileSuffix) {
        // 获取文件名称
        fileName = getFileName(fileName);

        httpServletResponse.setHeader(HttpHeaders.CONTENT_DISPOSITION,
                "attachment;filename*=utf-8''".concat(fileName).concat(fileSuffix));

    }

    /**
     * 渲染生成pdf文件
     *
     * @param httpServletResponse 响应
     * @param templatedData       模板数据
     * @param templateName        模板名称
     * @param fileName            文件名称
     * @param fileSuffix          文件后缀
     * @param isDownload          true: 下载 false：预览
     */
    @SneakyThrows(Throwable.class)
    public void freeMarkerRenderFileToPdf(HttpServletResponse httpServletResponse,
                                          Map<String, Object> templatedData,
                                          String templateName, String fileName, String fileSuffix,
                                          boolean isDownload) {

        if (isDownload) {
            download(httpServletResponse, fileName, fileSuffix);
        }
        //2、 输入流
        InputStream input =
                new ByteArrayInputStream(freeMarkerUtil.getPdfFile(templatedData, templateName).toByteArray());
        //3、 写出文件--输出流
        OutputStream out = httpServletResponse.getOutputStream();
        byte[] buff = new byte[1024];
        int index;
        //4、执行 写出操作
        while ((index = input.read(buff)) != -1) {
            out.write(buff, 0, index);
            out.flush();
        }
    }

    /**
     * 执行下载,多个pdf打包下载
     *
     * @param httpServletResponse 响应
     * @param templatedData       模板数据
     * @param templateName        模板名称
     * @param fileName            文件名称
     * @param fileSuffix          文件后缀
     */
    @SneakyThrows(Throwable.class)
    public void freeMarkerRenderFileDownloadToPdfForZip(HttpServletResponse httpServletResponse,
                                                        Map<String, Object> templatedData,
                                                        String templateName, String fileName, String fileSuffix) {

        download(httpServletResponse, fileName, fileSuffix);
        //2、 输入流
        ByteArrayOutputStream byteArrayOutputStream1 = freeMarkerUtil.getPdfFile(templatedData, templateName);
        ByteArrayOutputStream byteArrayOutputStream2 = freeMarkerUtil.getPdfFile(templatedData, templateName);
        //3、 写出文件--输出流
        @Cleanup
        OutputStream outputStream = httpServletResponse.getOutputStream();
        @Cleanup
        ZipArchiveOutputStream zipArchiveOutputStream = new ZipArchiveOutputStream(outputStream);
        zipArchiveOutputStream.setUseZip64(Zip64Mode.AsNeeded);
        zipArchiveOutputStream.setEncoding(String.valueOf(StandardCharsets.UTF_8));

        ArchiveEntry archiveEntry1 = new ZipArchiveEntry("1.pdf");
        ArchiveEntry archiveEntry2 = new ZipArchiveEntry("2.pdf");

        zipArchiveOutputStream.putArchiveEntry(archiveEntry1);
        zipArchiveOutputStream.write(byteArrayOutputStream1.toByteArray());
        zipArchiveOutputStream.putArchiveEntry(archiveEntry2);
        zipArchiveOutputStream.write(byteArrayOutputStream2.toByteArray());
        zipArchiveOutputStream.closeArchiveEntry();
    }


    /**
     * 获取文件名称
     *
     * @param fileName 文件名称
     * @return {@link String}
     */
    @SneakyThrows(Throwable.class)
    public String getFileName(String fileName) {
        return StrUtil.isNotBlank(fileName) ?
                URLEncoder.encode(fileName, String.valueOf(StandardCharsets.UTF_8)).replaceAll("\\+", "%20")
                : LocalDateTime.now().toString();
    }
}
